package com.detech.sboh.business.login.controller;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import com.detech.sboh.base.annotation.Log;
import com.detech.sboh.base.annotation.ProductSwagger;
import com.detech.sboh.base.constant.CacheConstants;
import com.detech.sboh.base.constant.Constants;
import com.detech.sboh.base.domain.R;
import com.detech.sboh.base.domain.RE;
import com.detech.sboh.base.enumtype.LogTypeEnum;
import com.detech.sboh.base.enumtype.ModuleEnum;
import com.detech.sboh.base.enumtype.MsgEnum;
import com.detech.sboh.base.redis.RedisUtils;
import com.detech.sboh.base.satoken.utils.LoginHelper;
import com.detech.sboh.business.login.service.LoginService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;

@RestController
@RequestMapping(value = "/login")
@Api(tags = "用户登录")
public class LoginController {

    @Autowired
    private LoginService loginService;

    @ApiOperation(value = "用户登录（PC端）", notes = "用户登录（PC端）")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true),
            @ApiImplicitParam(name="password",value="登录密码",dataType="string", paramType = "query", dataTypeClass=java.lang.String.class,required=true)
    })
    @RequestMapping(value = "/pcLogin",method = RequestMethod.POST)
    @ProductSwagger
    @Log(model = ModuleEnum.LOGIN,logType = LogTypeEnum.INFO,value = "用户登录（PC端）", saveDB = true,showParam = "username")
    public RE<SaTokenInfo> pcLogin(String username, String password) {
        SaTokenInfo tokenInfo = loginService.pcLogin(username, password);
        return R.ok(MsgEnum.LOGIN_SUCCESS.getMsg(),tokenInfo);
    }

    @ApiOperation(value = "用户登录（APP端）", notes = "用户登录（APP端）")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=String.class,required=true),
            @ApiImplicitParam(name="password",value="登录密码",dataType="string", paramType = "query", dataTypeClass=String.class,required=true)
    })
    @Log(model = ModuleEnum.LOGIN,logType = LogTypeEnum.INFO,value = "用户登录（APP端）", saveDB = true,showParam = "username")
    @PostMapping(value = "/appLogin")
    public RE appLogin(String username, String password) {
        SaTokenInfo tokenInfo = loginService.appLogin(username, password);
        return R.ok(MsgEnum.LOGIN_SUCCESS.getMsg(),tokenInfo);
    }

    @ApiOperation(value = "微信小程序端自动登录",notes = "适用于微信小程序已绑定用户帐号的情况")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="xcxCode",value="xcxCode",dataType="string", paramType = "query", dataTypeClass=String.class,required=true)
    })
    @Log(model = ModuleEnum.LOGIN,logType = LogTypeEnum.INFO,value = "微信小程序端自动登录", saveDB = true,showParam = "xcxCode")
    @PostMapping(value = "/xcxAutoLogin")
    public RE xcxAutoLogin(String xcxCode) {
        SaTokenInfo tokenInfo = loginService.xcxAutoLogin(xcxCode);
        return R.ok(MsgEnum.LOGIN_SUCCESS.getMsg(),tokenInfo);
    }

    @ApiOperation(value = "用户登录（微信小程序端）",notes = "如果微信小程序端自动登录接口返回响应码为401，则需要调用此接口，输入用户帐号密码进行认证绑定")
    @ApiOperationSupport( author = "方安伦")
    @ApiImplicitParams({
            @ApiImplicitParam(name="xcxCode",value="小程序随机code",dataType="string", paramType = "query", dataTypeClass=String.class,required=true),
            @ApiImplicitParam(name="username",value="用户帐号",dataType="string", paramType = "query", dataTypeClass=String.class,required=true),
            @ApiImplicitParam(name="password",value="登录密码",dataType="string", paramType = "query", dataTypeClass=String.class,required=true)
    })
    @Log(model = ModuleEnum.LOGIN,logType = LogTypeEnum.INFO,value = "用户登录（微信小程序端）", saveDB = true,showParam = "xcxCode,username")
    @PostMapping(value = "/xcxLogin")
    public RE xcxLogin(String xcxCode, String username, String password) {
        SaTokenInfo tokenInfo = loginService.xcxLogin(xcxCode,username, password);
        return R.ok(MsgEnum.LOGIN_SUCCESS.getMsg(),tokenInfo);
    }

    @ApiOperation("登出方法")
    @ApiOperationSupport( author = "方安伦")
    @Log(model = ModuleEnum.LOGIN,logType = LogTypeEnum.INFO,value = "用户登出", saveDB = false)
    @PostMapping(value = "/logout")
    public RE logout() {
        try {
            String username = LoginHelper.getUsername();
            String deviceType = LoginHelper.getLoginDeviceType().getDevice();
            StpUtil.logout();
            loginService.recordLogininfor(username, Constants.LOGOUT, MsgEnum.OPRATE_SUCCESS.getMsg(),deviceType);
        } catch (NotLoginException e) {
        }
        return R.ok();
    }

    /**
     * 获取验证码
     */
    @ApiOperation(value = "获取验证码", notes = "用户登录页面获取验证码，流方式返回，前台用img标签接收",httpMethod="POST")
    @RequestMapping(value = "/yzm")
    public void yzm(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 生成纯数字验证码
//        RandomGenerator randomGenerator = new RandomGenerator("0123456789", 4);
//        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(114, 42, 5, 3);
//        captcha.setGenerator(randomGenerator);
        // 生成字母和数字的验证码
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(140, 40, 5, 3);
        // 获取 redis key
        String key = CacheConstants.CAPTCHA_CODE_KEY + request.getSession().getId();
        // 保存验证码到redis,有效时间3分钟
        RedisUtils.setCacheObject(key, captcha.getCode(), Duration.ofMinutes(3));
        // 清空response
        response.reset();
        //设置返回文件类型
        response.setContentType("image/jpeg");
        // 禁止图像缓存。
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);
        ServletOutputStream outputStream = response.getOutputStream();
        // 将验证码写出到 response 的输出流中
        captcha.write(outputStream);
        // 刷新
        outputStream.flush();
        // 关闭流
        outputStream.close();
    }
}
